home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-03 | 40.7 KB | 1,481 lines | [TEXT/MPS ] |
- //----------------------------------------------------------------------------------------
- // UStream.cp
- // Copyright © 1990-96 by Apple Computer, Inc. All rights reserved.
- //
- // Originally written by Larry S. Rosenstein. Used by permission
- //----------------------------------------------------------------------------------------
-
- #ifndef __USTREAM__
- #include "UStream.h"
- #endif
-
- // MacApp
-
- #ifndef __GEOMETRY__
- #include "Geometry.h"
- #endif
-
- #ifndef __UFAILURE__
- #include "UFailure.h"
- #endif
-
- #ifndef __ULIST__
- #include "UList.h"
- #endif
-
- #ifndef __ULISTITERATOR__
- #include "UListIterator.h"
- #endif
-
- #ifndef __UCOREGLOBALS__
- #include "UCoreGlobals.h"
- #endif
-
- #ifndef __UCOREUTILITIES__
- #include "UCoreUtilities.h"
- #endif
-
- #ifndef __UMEMORY__
- #include "UMemory.h"
- #endif
-
- #ifndef __UPATCH__
- #include "UPatch.h"
- #endif
-
- // Toolbox
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #ifndef __LOWMEM__
- #include <LowMem.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
-
- // ANSI
-
- #ifndef __LIMITS__
- #include <limits.h>
- #endif
-
-
- //========================================================================================
- // CLASS TContext
- //========================================================================================
- #undef Inherited
- #define Inherited TObject
-
- #pragma segment MAStreamCreate
- MA_DEFINE_CLASS_M1(TContext,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TContext constructor
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- TContext::TContext() :
- fOtherObjects(NULL)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TContext::IContext:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- void TContext::IContext()
- {
- IObject();
-
- FailInfo fi;
- Try(fi)
- {
- fOtherObjects = NewList();
- fi.Success();
- }
- else
- {
- Free();
- fi.ReSignal();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TContext::Free:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamFree
-
- TContext::~TContext()
- {
- fOtherObjects = (TList *)FreeIfObject((TObject *)fOtherObjects);// don't call FreeList
- }
-
- //----------------------------------------------------------------------------------------
- // TContext::Clone:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- TObject* TContext::Clone()
-
- {
- MAVolatileInit(TContext * , aClonedContext, (TContext *)Inherited::Clone());
- aClonedContext->fOtherObjects = NULL; // so failure handler works
-
- FailInfo fi;
- Try(fi) // In case allocation fails, object is freed.
- {
- aClonedContext->fOtherObjects = (TList *)fOtherObjects->Clone();
- fi.Success();
- }
- else // Recover
- {
- aClonedContext->Free(); // Free the stream if it can't be initialized
- fi.ReSignal();
- }
-
- return aClonedContext;
- }
-
- //----------------------------------------------------------------------------------------
- // TContext::Add:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- LocalObjectNumber TContext::Add(TObject* objectToAdd,
- Boolean forceReplacement,
- Boolean& newEntry)
- {
- LocalObjectNumber retval = 0;
-
- // Look for object
- CObjectIterator iter(fOtherObjects);
-
- for (TObject * obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
- {
- if (objectToAdd == obj)
- {
- retval = iter.CurrentIndex();
- break;
- }
- }
-
- if (retval == 0)
- {
- fOtherObjects->InsertLast(objectToAdd);
- retval = fOtherObjects->GetSize();
- newEntry = TRUE;
- }
- else if (forceReplacement) // We force replacement
- {
- fOtherObjects->AtPut(retval, objectToAdd);
- newEntry = TRUE;
- }
- else
- newEntry = FALSE;
-
- return retval;
- }
-
- //----------------------------------------------------------------------------------------
- // TContext::Find:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- TObject* TContext::Find(LocalObjectNumber name)
- {
- return fOtherObjects->At(name);
- }
-
-
- //========================================================================================
- // CLASS TStream
- //========================================================================================
- #undef Inherited
- #define Inherited TObject
-
- #pragma segment MAStreamCreate
- MA_DEFINE_CLASS_M1(TStream,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TStream constructor
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- TStream::TStream() :
- fClassMap(NULL),
- fClassMapSize(0),
- fContext(NULL)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::IStream:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- void TStream::IStream()
- {
- IObject();
-
- FailInfo fi;
- Try(fi) // In case allocation fails, object is freed.
- {
- fClassMap = (HClassArray)NewPermHandle(0);
- fi.Success();
- }
- else // Recover
- {
- Free(); // Free the stream if it can't be initialized
- fi.ReSignal();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::AtEnd:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- Boolean TStream::AtEnd()
- {
- return (GetPosition() >= GetSize()) ? TRUE : FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::Free:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamFree
-
- TStream::~TStream()
- {
- fContext = (TContext *)FreeIfObject((TObject *)fContext);
- fClassMap = (HClassArray)DisposeIfHandle((Handle)fClassMap);
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::GetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TStream::GetPosition()
- {
- return 0;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::GetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TStream::GetSize()
- {
- return 0;
- }
-
-
- //----------------------------------------------------------------------------------------
- // TStream::LookupClassID: This returns the new class ID given a class ID found in the
- // stream, or kNilClass if it wasn't found. It does a simple linear search.
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TStream::LookupClassID(long id)
- {
- if (id != kNilClass)
- for (short i = 0; i < fClassMapSize; ++i)
- if ((*fClassMap)[i].fOldID == id)
- return (*fClassMap)[i].fNewID;
- return kNilClass;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamNever
-
- void TStream::ReadBytes(void* ,
- long)
- {
- SubClassResponsibility();
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadByte:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- Byte TStream::ReadByte()
- {
- Byte data;
-
- ReadBytes(&data, sizeof(Byte));
-
- return data;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadBoolean:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- Boolean TStream::ReadBoolean()
- {
- Boolean data;
-
- ReadBytes(&data, sizeof(Boolean));
-
- return data;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadCharacter: The trick here is that characters are represented as 2 bytes,
- // with the actual data in the low order byte.
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadCharacter(short& data)
- {
- data = 0; // Clear the high order byte.
- ReadBytes((char*) & data + 1, 1);
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadInteger:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- short TStream::ReadInteger()
- {
- short data;
-
- ReadBytes(&data, sizeof(short));
-
- return data;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadLong:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- long TStream::ReadLong()
- {
- long data;
-
- ReadBytes(&data, sizeof(long));
-
- return data;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadString:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadString(CString& data,
- short maxSize)
- {
- ReadBytes(&data, 1); // Read the length byte.
-
- if (data.Length() + 1 > maxSize)
- FailOSErr(paramErr); // Can't read that many bytes.
- else
- ReadBytes(&data[1], (long)data.Length());
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadHandle:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- Handle TStream::ReadHandle()
- {
- Handle aHandle = NULL;
-
- // read the size of the handle in from the stream
- Size itsSize = ReadLong();
-
- if (itsSize >= 0)
- {
- // allocate the handle
- aHandle = NewPermHandle(itsSize);
-
- // read the handle in from the stream
- FailInfo fi;
- Try(fi)
- {
- // Lock the handle and read into it from the stream.
- // We definitely need to lock the handle here because
- // the code in ReadBytes may move memory before reading
- // the data.
- SignedByte savedState = LockHandle(aHandle);
- FailMemError();
- ReadBytes(*aHandle, itsSize);
- HSetState(aHandle, savedState);
-
- fi.Success();
- }
- else // Recover
- {
- aHandle = DisposeIfHandle(aHandle);
- fi.ReSignal();
- }
- }
-
- return aHandle;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadStdObject:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- Boolean TStream::ReadStdObject(TObject*& data)
- {
- IDType itsSignature;
- long sizePosition;
- long objectSize;
- ClassName className;
- Boolean known;
-
- itsSignature = ReadIDType(); // Read the object's signature.
-
- sizePosition = GetPosition(); // Read its size and remember the current position.
- objectSize = ReadLong();
-
- ReadString(className, sizeof(MAName)); // Read its name.
-
- data = NULL;
-
- if (className.IsEmpty())
- data = (TObject *)ClassDesc::NewBySignature(itsSignature);
- else
- data = (TObject *)ClassDesc::NewByClassName(className);
-
- if (data)
- known = TRUE;
- else // Don't know about the class.
- {
- // If the streamID is kNilClass then the object was realy
- // NULL, which is a known object, otherwise the class
- // isn't available.
- known = FALSE;
-
- // Skip over the object's data.
- SetPosition(sizePosition + objectSize);// Skip over its data.
- }
-
- return known;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadObject:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- Boolean TStream::ReadObject(TObject*& data)
- {
- long streamID; // Class ID in stream.
- long currentID; // Class ID in program.
- long sizePosition;
- long objectSize;
- ClassName className;
- Boolean known;
-
- ReadBytes(&streamID, sizeof(long)); // Read the object's class ID.
-
- sizePosition = GetPosition(); // Read its size and remember the current position.
- objectSize = ReadLong();
-
- ReadString(className, sizeof(MAName)); // Read its name.
-
- if (className.IsEmpty()) // No class name. Must have seen the class
- // before, so convert the streamID to the
- // currentID.
- currentID = LookupClassID(streamID);
- else
- { // Get ID from name ...
- currentID = ClassDesc::GetClassDescFromClassName(className)->GetClassID();
- RegisterClassID(streamID, currentID); // ... and register the IDs.
- }
-
- data = NULL;
-
- if (currentID == kNilClass) // Don't know about the class.
- {
- // If the streamID is kNilClass then the object was realy
- // NULL, which is a known object, otherwise the class
- // isn't available.
- known = streamID == kNilClass;
-
- // Skip over the object's data.
- SetPosition(sizePosition + objectSize); // Skip over its data.
- }
- else
- { // Create the object.
- data = (TObject *)ClassDesc::NewByClassID((ClassID)currentID);
- known = TRUE;
- }
-
- return known;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadPoint:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- CPoint TStream::ReadPoint()
- {
- CPoint data;
-
- ReadBytes(&data, sizeof(CPoint));
-
- return data;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadVPoint:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadVPoint(VPoint& data)
- {
- ReadBytes(&data, sizeof(VPoint));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadRect:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadRect(CRect& data)
- {
- ReadBytes(&data, sizeof(CRect));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadVRect:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadVRect(VRect& data)
- {
- ReadBytes(&data, sizeof(VRect));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadRGBColor:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadRGBColor(CRGBColor& data)
- {
- ReadBytes(&data, sizeof(CRGBColor));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadIDType:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- IDType TStream::ReadIDType()
- {
- IDType data;
-
- ReadBytes(&data, sizeof(IDType));
-
- return data;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadStreamObject:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- Boolean TStream::ReadStreamObject(TObject*& data)
- {
- Boolean known = FALSE;
- short delimiter;
- LocalObjectNumber itsObjectNumber;
- TContext * itsContext = GetContext();
-
- delimiter = ReadInteger();
-
- if (delimiter == kNullObject)
- {
- data = NULL;
- known = TRUE;
- }
- else if (delimiter == kLocalObjectNumber)
- {
- ReadBytes(&itsObjectNumber, sizeof(LocalObjectNumber));
- if (itsContext)
- data = itsContext->Find(itsObjectNumber);
- #if qDebugMsg
- else
- ProgramBreak("###Need a TContext in TStream::ReadStreamObject.");
- #endif
-
- if (data)
- known = TRUE;
- }
- else
- {
- if (delimiter == kClassIDAndClassname)
- known = ReadObject(data); // Create an uninitialized object.
- else if (delimiter == kSignatureAndClassname)
- known = ReadStdObject(data); // Create an uninitialized object by signature.
- #if qDebugMsg
- else
- ProgramBreak("###Unknown delimiter in TStream::ReadStreamObject.");
- #endif
-
- if (known)
- {
- Boolean newEntry = FALSE;
- if (itsContext)
- itsObjectNumber = itsContext->Add(data, kDontForceReplacement, newEntry);
-
- FailInfo fi;
- Try(fi)
- {
- if (data) // If we got an object, then tell it to initialize itself.
- data->ReadFrom(this);
- fi.Success();
- }
- else
- {
- data = NULL; // Data should have been freed by ReadFields
- // so just make sure that we return a null
- // null reference.
- fi.ReSignal();
- }
- }
- }
- return known;
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::ReadWordAlign:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TStream::ReadWordAlign()
- {
- if (odd(GetPosition()))
- {
- Byte junk;
- ReadBytes(&junk, sizeof(Byte));
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::RegisterClassID: This simply adds the mapping to the end of the list. It does
- // not check to see if the mapping exists already.
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void TStream::RegisterClassID(long oldID,
- long newID)
- {
- if (oldID != kNilClass)
- {
- ++fClassMapSize;
- SetPermHandleSize((Handle)fClassMap, fClassMapSize * sizeof(ClassIDEntry));
-
- (*fClassMap)[fClassMapSize - 1].fOldID = oldID;
- (*fClassMap)[fClassMapSize - 1].fNewID = newID;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::SetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void TStream::SetPosition(long /* newPosition */)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::SetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void TStream::SetSize(long /* newSize */)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamNever
-
- void TStream::WriteBytes(const void* ,
- long)
- {
- SubClassResponsibility();
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteByte:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteByte(Byte data)
- {
- WriteBytes(&data, sizeof(Byte));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteBoolean:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteBoolean(Boolean data)
- {
- WriteBytes(&data, sizeof(Boolean));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteCharacter:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteCharacter(short data)
- {
- WriteBytes((char*) & data + 1, 1); // Again, the data is in the low order byte.
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteInteger:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteInteger(short data)
-
- {
- WriteBytes(&data, sizeof(short));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteLong:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteLong(long data)
-
- {
- WriteBytes(&data, sizeof(long));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteStreamObject:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteStreamObject(TObject* data,
- Boolean stdObject)
- {
- long sizePosition;
- short delimiter = kClassIDAndClassname;
- LocalObjectNumber itsObjectNumber;
- Boolean newEntry = FALSE;
-
- if (!data)
- delimiter = kNullObject;
- else
- {
- if (stdObject)
- delimiter = kSignatureAndClassname;
-
- TContext * itsContext = GetContext();
- if (itsContext)
- {
- itsObjectNumber = itsContext->Add(data, kDontForceReplacement, newEntry);
- if (!newEntry)
- delimiter = kLocalObjectNumber;
- }
- }
-
- WriteInteger(delimiter);
-
- if (delimiter == kNullObject)
- ; // write nothing
- else if (delimiter == kLocalObjectNumber)
- WriteBytes(&itsObjectNumber, sizeof(LocalObjectNumber));
- else
- {
- if (delimiter == kClassIDAndClassname)
- WriteObject(data, sizePosition); // Write the object header.
- else
- WriteStdObject(data, sizePosition); // Write the object header.
-
- if (data) // Write the private data.
- data->WriteTo(this);
-
- WriteObjectSize(sizePosition); // Write the object size.
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteStdObject:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteStdObject(TObject* data,
- long& sizePosition)
- {
- IDType itsSignature = data ? data->GetStandardSignature() : kNoIdentifier;
-
- WriteIDType(itsSignature); // Write the signature.
-
- sizePosition = GetPosition(); // Return the position of the object size
-
- WriteLong(LONG_MAX); // Write a dummy size (maximum object size).
-
- ClassName className;
- if (data) // data is not NULL
- {
- data->GetClassName(className); // Get the actual class name.
- if (itsSignature != kNoIdentifier)
- {
- const ClassDesc* signatureClassDesc = ClassDesc::GetClassDescFromSignature(itsSignature);
- if (signatureClassDesc != NULL && signatureClassDesc == data->GetClassDescDynamic())
- className.Empty(); // then no need for class name in stream
- }
- }
-
- WriteString(className); // Write the class name (which may be empty).
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteObject:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteObject(TObject* data,
- long& sizePosition)
- {
- long streamID = data ? data->GetClassID() : kNilClass;
-
- WriteBytes(&streamID, sizeof(long)); // Write the class ID.
-
- sizePosition = GetPosition(); // Remember the position of the object size
- // in the stream.
-
- WriteLong(LONG_MAX); // Write a dummy size (maximum object size).
-
- ClassName className;
- if ((data) && (LookupClassID(streamID) == kNilClass))
- // data is not NULL, and this is the first object of the class.
- {
- data->GetClassName(className); // Get the actual class name.
-
- // Register the ID, so we don't write the class name the next time
- // we write an object of this class. The second parameter
- // doesn't matter, as long as it isn't kNilClass.
- RegisterClassID(streamID, streamID);
- }
-
- WriteString(className); // Write the class name (which may be empty).
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteObjectSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- // This fills in the object's size at the position passed in.
- void TStream::WriteObjectSize(long sizePosition)
- {
- long currentPosition = GetPosition(); // Remember where we are.
- SetPosition(sizePosition); // Go back to position of size.
-
- WriteLong(currentPosition - sizePosition); // Write the size.
-
- SetPosition(currentPosition); // Go back to where we were.
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WritePoint:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WritePoint(CPoint data)
- {
- WriteBytes(&data, sizeof(CPoint));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteVPoint:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteVPoint(const VPoint& data)
- {
- WriteBytes(&data, sizeof(VPoint));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteRect:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteRect(const CRect& data)
- {
- WriteBytes(&data, sizeof(CRect));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteVRect:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteVRect(const VRect& data)
- {
- WriteBytes(&data, sizeof(VRect));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteRGBColor:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteRGBColor(const CRGBColor& data)
- {
- WriteBytes(&data, sizeof(CRGBColor));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteIDType:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteIDType(const IDType data)
-
- {
- WriteBytes(&data, sizeof(IDType));
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteWordAlign:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteWordAlign()
- {
- if (odd(GetPosition()))
- {
- Byte junk = 0;
- WriteBytes(&junk, sizeof(Byte));
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteString:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteString(const CString& data)
- {
- WriteBytes(&data, ((long)data.Length()) + 1);// + 1 to include length byte.
- }
-
- //----------------------------------------------------------------------------------------
- // TStream::WriteHandle:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TStream::WriteHandle(const Handle aHandle)
- {
- if (aHandle == NULL)
- WriteLong(-1);
- else
- {
- // write the size of the handle
- Size itsSize = GetHandleSize(aHandle);
- WriteLong(itsSize);
-
- // Write the contents of the handle.
- // We definitely need to lock the handle here because
- // the code in WriteBytes may move memory before reading
- // the data.
- SignedByte savedState = LockHandle(aHandle);
- FailMemError();
- WriteBytes(*aHandle, itsSize);
- HSetState(aHandle, savedState);
- }
- }
-
-
- //========================================================================================
- // CLASS THandleStream
- //========================================================================================
- #undef Inherited
- #define Inherited TStream
-
- #pragma segment MAStreamCreate
- MA_DEFINE_CLASS_M1(THandleStream,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // THandleStream constructor
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- THandleStream::THandleStream()
- {
- fGrowthSize = 1;
- fHandle = NULL;
- fPosition = 0;
- fSavedState = 0;
- fSize = 0;
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::IHandleStream:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- void THandleStream::IHandleStream(Handle itsHandle,
- long growth)
- {
- IStream();
-
- fGrowthSize = growth;
- fPosition = 0;
- if (itsHandle)
- {
- if (IsAResource(itsHandle))
- {
- FailInfo fi;
- Try(fi)
- {
- ::LoadResource(itsHandle); // ensure it's loaded in memory
- FailResError();
- fi.Success();
- }
- else
- {
- Free();
- fi.ReSignal();
- }
- }
- fSize = ::GetHandleSize(itsHandle);
- fSavedState = ::HGetState(itsHandle);
- ::HNoPurge(itsHandle); // ensure it's not purgeable
- fHandle = itsHandle;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::Free:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamFree
-
- THandleStream::~THandleStream()
- {
- if (fHandle)
- {
- SetSize(GetPosition()); // Trim the handle to its current position.
- ::HSetState(fHandle, fSavedState);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::GetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long THandleStream::GetPosition() // override
- {
- return fPosition;
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::GetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long THandleStream::GetSize() // override
- {
- return fSize;
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::GrowthSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long THandleStream::GrowthSize(long needed)
- {
- return Max(fGrowthSize, needed);
- }
-
-
- //----------------------------------------------------------------------------------------
- // THandleStream::SetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void THandleStream::SetPosition(long newPosition)// override
- {
- OSErr err;
-
- if (newPosition < 0) // Same error returned by File Manager.
- FailOSErr(posErr);
- else if (newPosition > fSize) // Hit the end of the stream.
- {
- newPosition = fSize; // We still want to position to end of the stream.
- err = eofErr;
- }
- else
- err = noErr;
-
- fPosition = newPosition;
- FailOSErr(err);
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::SetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void THandleStream::SetSize(long newSize) // override
- {
- SetPermHandleSize(fHandle, newSize);
-
- if (newSize < fPosition) // If we shrunk the size, then adjust position and size
- fPosition = newSize;
-
- fSize = newSize;
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::ReadBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void THandleStream::ReadBytes(void* p,
- long count) // override
- {
- OSErr err = noErr;
-
- register long available = fSize - fPosition;// Bytes available in the stream.
-
- if (available < count) // About to read past end of stream.
- {
- count = available;
- err = eofErr;
- }
-
- if (count > 0) // Move the bytes.
- {
- MABlockMove(*fHandle + fPosition, p, count);
- fPosition += count;
- }
- else if (count < 0)
- err = paramErr; // Negative request count.
-
- FailOSErr(err);
- }
-
- //----------------------------------------------------------------------------------------
- // THandleStream::WriteBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void THandleStream::WriteBytes(const void* p,
- long count) // override
- {
- if (count < 0)
- FailOSErr(paramErr); // Negtive request count.
-
- long available = fSize - fPosition; // Bytes available in the stream.
-
- if (available < count) // Grow the handle to accommodate request.
- {
- // code as 2 statements to avoid interference of memory move in call to GrowthSize
- long itsGrowthSize = GrowthSize(count - available);
- SetSize(fSize + itsGrowthSize);
- }
-
- MABlockMove(p, *fHandle + fPosition, count);// Move the bytes.
-
- fPosition += count; // Advance the position.
-
- if (fPosition > fSize) // Adjust the size if necessary.
- fSize = fPosition;
- }
-
-
- //========================================================================================
- // CLASS TCountingStream
- //========================================================================================
- #undef Inherited
- #define Inherited TStream
-
- #pragma segment MAStreamCreate
- MA_DEFINE_CLASS_M1(TCountingStream,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TCountingStream constructor
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- TCountingStream::TCountingStream()
- {
- fPosition = 0;
- fSize = 0;
- }
-
- //----------------------------------------------------------------------------------------
- // TCountingStream destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TCountingStream::~TCountingStream()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TCountingStream::GetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TCountingStream::GetPosition() // override
- {
- return fPosition;
- }
-
- //----------------------------------------------------------------------------------------
- // TCountingStream::SetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void TCountingStream::SetPosition(long newPosition)// Override
- {
- OSErr err;
-
- if (newPosition < 0) // Same error returned by File Manager.
- FailOSErr(posErr);
- else if (newPosition > fSize) // Hit the end of the stream.
- {
- newPosition = fSize; // We still want to position to end of the stream.
- err = eofErr;
- }
- else
- err = noErr;
-
- fPosition = newPosition;
- FailOSErr(err);
- }
-
- //----------------------------------------------------------------------------------------
- // TCountingStream::GetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TCountingStream::GetSize() // override
- {
- return fSize;
- }
-
- //----------------------------------------------------------------------------------------
- // TCountingStream::SetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
- void TCountingStream::SetSize(long newSize) // Override
- {
- if (newSize < fPosition) // If we shrunk the size, then we have to adjust the position.
- fPosition = newSize;
- fSize = newSize;
- }
-
-
- //----------------------------------------------------------------------------------------
- // TCountingStream::WriteBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- void TCountingStream::WriteBytes(const void* /* p */ ,
- long count) // override
- {
- if (count < 0) // Can't write negative number of bytes.
- FailOSErr(paramErr);
-
- fPosition += count; // Advance the position.
-
- if (fPosition > fSize) // Adjust the size if necessary.
- fSize = fPosition;
- }
-
-
-
- //========================================================================================
- // CLASS TResourceStream
- //========================================================================================
- #undef Inherited
- #define Inherited TStream
-
- #pragma segment MAStreamCreate
- MA_DEFINE_CLASS_M1(TResourceStream,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TResourceStream constructor
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- TResourceStream::TResourceStream()
- {
- fResource = NULL;
- fPosition = 0;
- fSize = 0;
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TResourceStream::~TResourceStream()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::IResourceStream:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- void TResourceStream::IResourceStream(ResType theType,
- ResNumber theID)
- {
- IStream();
-
- FailInfo fi;
- Try(fi)
- {
- short oldResLoad = LMGetResLoad();
- SetResLoad(FALSE);
- fResource = GetResource(theType, theID);
- SetResLoad(oldResLoad);
- FailNILResource(fResource);
-
- fSize = GetResourceSizeOnDisk(fResource);
- FailResError();
-
- fi.Success();
- }
- else
- {
- Free();
- fi.ReSignal();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::GetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TResourceStream::GetPosition() // override
- {
- return fPosition;
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::SetPosition:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void TResourceStream::SetPosition(long newPosition)// override
- {
- fPosition = newPosition;
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::GetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- long TResourceStream::GetSize()
- {
- return fSize;
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::SetSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- void TResourceStream::SetSize(long newSize) // override
- {
- SetResourceSize(fResource, newSize);
- FailResError();
-
- fSize = newSize; // update if successfull
-
- if (newSize < fPosition) // If we shrunk the size, then we have to adjust the position.
- fPosition = newSize;
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::WriteBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MASectionWrite
-
- void TResourceStream::WriteBytes(const void* p,
- long count)
- {
- register long minSize = GetPosition() + count;
- if (minSize > GetSize())
- SetSize(minSize); // increase the size before writing
- WritePartialResource(fResource, GetPosition(), p, count);
- FailResError();
-
- SetPosition(minSize); // Advance the position.
- }
-
- //----------------------------------------------------------------------------------------
- // TResourceStream::ReadBytes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- void TResourceStream::ReadBytes(void* p,
- long count) // override
- {
- register long minToRead = Min(count, GetSize() - GetPosition());
- ReadPartialResource(fResource, GetPosition(), p, minToRead);
- FailResError();
-
- SetPosition(GetPosition() + minToRead); // Advance the position.
- }
-
- //----------------------------------------------------------------------------------------
- // End of UStream.cp
-
- #pragma segment Inline
-
-